package logic

import (
	"context"
	"gozero-microservices/user-service/rpc/internal/model"
	"gozero-microservices/user-service/rpc/internal/svc"
	"gozero-microservices/user-service/rpc/types"
	"gozero-microservices/user-service/rpc/types/user"
	"gozero-microservices/user-service/rpc/utils"
	"math"
	"strings"

	"github.com/zeromicro/go-zero/core/logx"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

/*
 +----------------------------------------------------------------------
 + Title        : UserLogic
 + Author       : huwl
 + Version      : 1.0.0
 + Initial-Time : 2025-08-08
 + Last-time    : 这个文件最后修改的时间 + 修改人的名称
 + Desc         : 用户逻辑
 +----------------------------------------------------------------------
*/

type UserLogic struct {
	BaseLogic
}

/**
 * 创建用户逻辑实例
 *
 * @param context.Context ctx ----------------------必传
 * @param *svc.ServiceContext svcCtx ---------------必传
 * @return *UserLogic
 * @author huwl
 * @date 2025/10/14 12:54:03
 */
func NewUserLogicInstance(ctx context.Context, svcCtx *svc.ServiceContext) *UserLogic {
	return &UserLogic{
		BaseLogic{
			Ctx:    ctx,
			SvcCtx: svcCtx,
			Logger: logx.WithContext(ctx),
		},
	}
}

/**
 * 新增
 *
 * @param string Name -------------------------非必传,姓名
 * @param string Nick -------------------------非必传,昵称
 * @param string Email ------------------------非必传,邮箱
 * @param string Username ---------------------必传,用户名
 * @param string Password ---------------------非必传,密码
 * @param string AvatarUrl --------------------非必传,头像
 * @param uint32 Source -----------------------非必传,来源
 * @param uint32 Level ------------------------非必传,级别
 * @param string Mobile -----------------------必传,手机
 * @param uint32 Gender -----------------------非必传,性别
 * @param uint32 ProvinceId -------------------非必传,省Id
 * @param uint32 CityId -----------------------非必传,市Id
 * @param uint32 DistrictId -------------------非必传,区Id
 * @param uint32 Score ------------------------非必传,积分
 * @param int32 Balance -----------------------非必传,余额
 * @param int32 Status ------------------------非必传,状态
 * @param string Note -------------------------非必传,备注
 * @return *user.UserResult, error
 * @author huwl
 * @date 2025/10/20 18:51:38
 */
func (logic *UserLogic) AddUser(in *user.AddUserRequest) (*user.UserResult, error) {
	if in.Username == "" {
		return nil, status.Errorf(codes.InvalidArgument, "用户名不能为空")
	}
	if !utils.CheckMobile(in.Mobile) {
		return nil, status.Errorf(codes.InvalidArgument, "手机格式错误")
	}
	if in.Email != "" && !utils.CheckEmail(in.Email) {
		return nil, status.Errorf(codes.Aborted, "邮箱格式错误")
	}

	// 判断用户名唯一性
	total, err := logic.SvcCtx.UserModel.GetResultsByTotal(logic.Ctx, map[string]interface{}{
		"username":    in.Username,
		"status <> ?": -2,
	})
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}
	if total > 0 {
		return nil, status.Errorf(codes.Aborted, "用户名已存在")
	}

	// 判断手机号唯一性
	total, err = logic.SvcCtx.UserModel.GetResultsByTotal(logic.Ctx, map[string]interface{}{
		"mobile":      in.Mobile,
		"status <> ?": -2,
	})
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}
	if total > 0 {
		return nil, status.Errorf(codes.Aborted, "手机号已存在")
	}

	bcryptPassword := ""
	if in.Password != "" {
		bcryptPassword, _ = utils.Bcrypt(in.Password)
	}
	// 操作数据库
	_, err = logic.SvcCtx.UserModel.Insert(logic.Ctx, &model.MallUser{
		Name:       in.Name,
		Nick:       in.Nick,
		Email:      in.Email,
		Username:   in.Username,
		Password:   bcryptPassword,
		AvatarUrl:  in.AvatarUrl,
		Source:     uint8(in.Source),
		Level:      uint8(in.Level),
		Mobile:     in.Mobile,
		Gender:     uint8(in.Gender),
		ProvinceId: uint16(in.ProvinceId),
		CityId:     uint16(in.CityId),
		DistrictId: uint16(in.DistrictId),
		Score:      uint16(in.Score),
		Balance:    in.Balance,
		Status:     int8(in.Status),
		Token:      in.Token,
		Note:       in.Note,
		CreateTime: types.Now(),
	})
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}

	return &user.UserResult{
		Code: 200,
		Msg:  "新增用户成功",
	}, nil
}

/**
 * 删除
 *
 * @param string ids --------------------------必传,Id
 * @return *user.UserResult, error
 * @author huwl
 * @date 2025/10/20 18:51:38
 */
func (logic *UserLogic) DeleteUser(in *user.DeleteUserRequest) (*user.UserResult, error) {
	if in.Ids == "" {
		return nil, status.Errorf(codes.InvalidArgument, "用户Id错误")
	}

	// 操作数据库
	err := logic.SvcCtx.UserModel.EditByParams(logic.Ctx, map[string]interface{}{
		"status": -2,
	}, map[string]interface{}{
		"uid IN (?)": utils.IntSplit(strings.TrimRight(in.Ids, ","), ","),
	})
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}

	return &user.UserResult{
		Code: 200,
		Msg:  "删除用户成功",
	}, nil
}

/**
 * 编辑
 *
 * @param uint64 Uid --------------------------必传,Id
 * @param string Name -------------------------非必传,姓名
 * @param string Nick -------------------------非必传,昵称
 * @param string Email ------------------------非必传,邮箱
 * @param string Username ---------------------非必传,用户名
 * @param string Password ---------------------非必传,密码
 * @param string AvatarUrl --------------------非必传,头像
 * @param uint32 Source -----------------------非必传,来源
 * @param uint32 Level ------------------------非必传,级别
 * @param string Mobile -----------------------非必传,手机
 * @param uint32 Gender -----------------------非必传,性别
 * @param uint32 ProvinceId -------------------非必传,省Id
 * @param uint32 CityId -----------------------非必传,市Id
 * @param uint32 DistrictId -------------------非必传,区Id
 * @param uint32 Score ------------------------非必传,积分
 * @param int32 Balance -----------------------非必传,余额
 * @param string Note -------------------------非必传,备注
 * @return *user.UserResult, error
 * @author huwl
 * @date 2025/10/21 19:43:32
 */
func (logic *UserLogic) EditUser(in *user.EditUserRequest) (*user.UserResult, error) {
	params := map[string]interface{}{}
	if in.Uid <= 0 {
		return nil, status.Errorf(codes.InvalidArgument, "用户Id错误")
	}

	if in.Name != "" {
		params["name"] = in.Name
	}
	if in.Nick != "" {
		params["nick"] = in.Nick
	}
	if in.Email != "" {
		if !utils.CheckEmail(in.Email) {
			return nil, status.Errorf(codes.InvalidArgument, "邮箱格式错误")
		}

		params["email"] = in.Email
	}
	if in.Username != "" {
		// 判断用户名唯一性
		// SELECT * FROM `mall_user` where username="轮墓边狱" and status <> -2 and uid <> 2212;
		// 查询排除当前用户,其他用户名为xxx的用户，为啥要排除自己因为编辑的时候有可能提交的是自己的用户名
		// 当提交的是自己的用户名是允许的
		total, err := logic.SvcCtx.UserModel.GetResultsByTotal(logic.Ctx, map[string]interface{}{
			"username":    in.Username,
			"status <> ?": -2,
			"uid <> ?":    in.Uid,
		})
		if err != nil {
			return nil, status.Errorf(codes.Aborted, err.Error())
		}
		if total > 0 {
			return nil, status.Errorf(codes.Aborted, "用户名已存在")
		}

		params["username"] = in.Username
	}
	if in.Password != "" {
		bcryptPassword, _ := utils.Bcrypt(in.Password)
		params["password"] = bcryptPassword
	}
	if in.AvatarUrl != "" {
		params["avatar_url"] = in.AvatarUrl
	}
	if in.Source > 0 {
		params["source"] = in.Source
	}
	if in.Level > 0 {
		params["level"] = in.Level
	}
	if in.Mobile != "" {
		if !utils.CheckMobile(in.Mobile) {
			return nil, status.Errorf(codes.InvalidArgument, "手机号格式错误")
		}

		// 判断手机号唯一性
		// SELECT * FROM `mall_user` where mobile="178302122323" and status <> -2 and uid <> 2212;
		// 查询排除当前用户,其他手机号为xxx的用户，为啥要排除自己因为编辑的时候有可能提交的是自己的手机号
		// 当提交的是自己的手机号是允许的
		total, err := logic.SvcCtx.UserModel.GetResultsByTotal(logic.Ctx, map[string]interface{}{
			"mobile":      in.Mobile,
			"status <> ?": -2,
			"uid <> ?":    in.Uid,
		})
		if err != nil {
			return nil, status.Errorf(codes.Aborted, err.Error())
		}
		if total > 0 {
			return nil, status.Errorf(codes.Aborted, "手机号已存在")
		}

		params["mobile"] = in.Mobile
	}
	if in.Gender > 0 {
		params["gender"] = in.Gender
	}
	if in.ProvinceId > 0 {
		params["province_id"] = in.ProvinceId
	}
	if in.CityId > 0 {
		params["city_id"] = in.CityId
	}
	if in.DistrictId > 0 {
		params["district_id"] = in.DistrictId
	}
	if in.Score > 0 {
		params["score"] = in.Score
	}
	if in.Balance >= 0 {
		params["balance"] = in.Balance
	}
	if in.Note != "" {
		params["note"] = in.Note
	}

	// 操作数据库
	err := logic.SvcCtx.UserModel.EditByPrimaryKey(logic.Ctx, params, in.Uid, "uid")
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}

	return &user.UserResult{
		Code: 200,
		Msg:  "编辑用户成功",
	}, nil
}

/**
 * 编辑
 *
 * @param string Ids --------------------------必传,Id
 * @param int32 Status ------------------------非必传,状态
 * @return *user.UserResult, error
 * @author huwl
 * @date 2025/10/21 19:43:32
 */
func (logic *UserLogic) EditStatusUser(in *user.EditStatusUserRequest) (*user.UserResult, error) {
	uids := strings.TrimRight(in.Ids, ",")
	if uids == "" {
		return nil, status.Errorf(codes.InvalidArgument, "用户Id错误")
	}
	if !utils.IsContainNumber[int8]([]int8{-1, 1}, int8(in.Status)) {
		return nil, status.Errorf(codes.InvalidArgument, "用户状态错误")
	}

	// 操作数据库
	err := logic.SvcCtx.UserModel.EditByParams(logic.Ctx, map[string]interface{}{
		"status": in.Status,
	}, map[string]interface{}{
		"uid IN (?)": utils.IntSplit(uids, ","),
	})
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}

	message := ""
	if in.Status == 1 {
		message = "启用用户"
	} else {
		message = "禁用用户"
	}

	return &user.UserResult{
		Code: 200,
		Msg:  message + "成功",
	}, nil
}

/**
 * 详情
 *
 * @param uint64 Uid --------------------------必传,Id
 * @param int32 IsHaveUserAlbum ---------------非必传,是否需要相册
 * @return *user.UserResponse, error
 * @author huwl
 * @date 2025/10/20 18:51:38
 */
func (logic *UserLogic) UserDetail(in *user.UserDetailRequest) (*user.UserResponse, error) {
	if in.Uid <= 0 {
		return nil, status.Errorf(codes.InvalidArgument, "用户Id错误")
	}

	// 操作数据库
	userRes, err := logic.SvcCtx.UserModel.FindOne(logic.Ctx, int64(in.Uid))
	if err != nil {
		if strings.Contains(err.Error(), "no rows in result set") {
			return nil, status.Errorf(codes.Aborted, "用户信息错误")
		}

		return nil, status.Errorf(codes.Aborted, err.Error())
	}
	if userRes.Status == -2 {
		return nil, status.Errorf(codes.Aborted, "用户信息错误")
	}

	return &user.UserResponse{
		User: &user.User{
			Uid:        uint64(userRes.Uid),
			Name:       userRes.Name,
			Nick:       userRes.Nick,
			Email:      userRes.Email,
			Username:   userRes.Username,
			Password:   userRes.Password,
			AvatarUrl:  userRes.AvatarUrl,
			Source:     uint32(userRes.Source),
			Level:      uint32(userRes.Level),
			Mobile:     userRes.Mobile,
			Gender:     uint32(userRes.Gender),
			ProvinceId: uint32(userRes.ProvinceId),
			CityId:     uint32(userRes.CityId),
			DistrictId: uint32(userRes.DistrictId),
			Score:      uint32(userRes.Score),
			Status:     int32(userRes.Status),
			Note:       userRes.Note,
			CreateTime: userRes.CreateTime.String(),
			UpdateTime: userRes.UpdateTime.String(),
		},
	}, nil
}

/**
 * 获取单条用户信息
 *
 * @param string Name -------------------------非必传,姓名
 * @param string Nick -------------------------非必传,昵称
 * @param string Username ---------------------非必传,用户名
 * @param uint32 Source -----------------------非必传,来源
 * @param uint32 Level ------------------------非必传,级别
 * @param string Mobile -----------------------非必传,手机号
 * @param uint32 Gender -----------------------非必传,性别
 * @param uint32 ProvinceId -------------------非必传,省Id
 * @param uint32 CityId -----------------------非必传,市Id
 * @param uint32 DistrictId -------------------非必传,区Id
 * @param string Status -----------------------非必传,状态支持多个：1,-1
 * @return *user.UserResponse, error
 * @author huwl
 */
func (logic *UserLogic) Row(in *user.QueryUserRequest) (*user.UserResponse, error) {
	params := map[string]interface{}{
		"status <> ?": -2,
	}

	if in.Name != "" {
		params["name"] = in.Name
	}
	if in.Nick != "" {
		params["nick"] = in.Nick
	}
	if in.Email != "" {
		params["email"] = in.Email
	}
	if in.Username != "" {
		params["username"] = in.Username
	}
	if in.Source > 0 {
		params["source"] = in.Source
	}
	if in.Level > 0 {
		params["level"] = in.Level
	}
	if in.Mobile != "" {
		params["mobile"] = in.Mobile
	}
	if in.Gender > 0 {
		params["gender"] = in.Gender
	}
	if in.ProvinceId > 0 {
		params["province_id"] = in.ProvinceId
	}
	if in.CityId > 0 {
		params["city_id"] = in.CityId
	}
	if in.DistrictId > 0 {
		params["district_id"] = in.DistrictId
	}
	if in.Status != "all" {
		params["status IN (?)"] = utils.IntSplit(in.Status, ",")
	}

	// 数据库操作
	var userRes model.MallUser
	err := logic.SvcCtx.UserModel.Row(logic.Ctx, &userRes, params)
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}

	return &user.UserResponse{
		User: &user.User{
			Uid:        uint64(userRes.Uid),
			Name:       userRes.Name,
			Nick:       userRes.Nick,
			Email:      userRes.Email,
			Username:   userRes.Username,
			Password:   userRes.Password,
			AvatarUrl:  userRes.AvatarUrl,
			Source:     uint32(userRes.Source),
			Level:      uint32(userRes.Level),
			Mobile:     userRes.Mobile,
			Gender:     uint32(userRes.Gender),
			ProvinceId: uint32(userRes.ProvinceId),
			CityId:     uint32(userRes.CityId),
			DistrictId: uint32(userRes.DistrictId),
			Score:      uint32(userRes.Score),
			Status:     int32(userRes.Status),
			Note:       userRes.Note,
			CreateTime: userRes.CreateTime.String(),
			UpdateTime: userRes.UpdateTime.String(),
		},
	}, nil
}

/**
 * 列表
 *
 * @param uint64 Uid --------------------------非必传,用户Id
 * @param string Uids -------------------------非必传,用户Id多个
 * @param string Name -------------------------非必传,姓名
 * @param string Nick -------------------------非必传,昵称
 * @param string Email ------------------------非必传,邮箱
 * @param string Username ---------------------非必传,用户名
 * @param uint32 Source -----------------------非必传,来源
 * @param uint32 Level ------------------------非必传,级别
 * @param string Mobile -----------------------非必传,手机号
 * @param uint32 Gender -----------------------非必传,性别
 * @param uint32 ProvinceId -------------------非必传,省Id
 * @param uint32 CityId -----------------------非必传,市Id
 * @param uint32 DistrictId -------------------非必传,区Id
 * @param string Status -----------------------非必传,状态
 * @param string StartCreateTime --------------非必传,开始创建时间
 * @param string EndCreateTime ----------------非必传,结束创建时间
 * @param string SortField --------------------非必传,排序字段
 * @param string SortType ---------------------非必传,排序方式
 * @param int32 PageSize ----------------------非必传,条数
 * @param uint32 Page -------------------------非必传,页码
 * @return *user.UserListResponse, error
 * @author huwl
 */
func (logic *UserLogic) UserList(in *user.QueryUserRequest) (*user.UserListResponse, error) {
	params := map[string]interface{}{
		"status <> ?": -2,
	}

	page := in.Page
	pageSize := in.PageSize
	sortType := in.SortType
	sortField := in.SortField

	if in.Uid > 0 {
		params["uid"] = in.Uid
	}
	if in.Uids != "" {
		params["uid IN (?)"] = utils.IntSplit(strings.TrimRight(in.Uids, ","), ",")
	}
	if in.Name != "" {
		params["name"] = in.Name
	}
	if in.Nick != "" {
		params["nick"] = in.Nick
	}
	if in.Email != "" {
		params["email"] = in.Email
	}
	if in.Username != "" {
		params["username"] = in.Username
	}
	if in.Source > 0 {
		params["source"] = in.Source
	}
	if in.Level > 0 {
		params["level"] = in.Level
	}
	if in.Mobile != "" {
		params["mobile"] = in.Mobile
	}
	if in.Gender > 0 {
		params["gender"] = in.Gender
	}
	if in.ProvinceId > 0 {
		params["province_id"] = in.ProvinceId
	}
	if in.CityId > 0 {
		params["city_id"] = in.CityId
	}
	if in.DistrictId > 0 {
		params["district_id"] = in.DistrictId
	}
	if in.Status != "all" {
		params["status IN (?)"] = utils.IntSplit(in.Status, ",")
	}
	if in.StartCreateTime != "" {
		params["create_time >= ?"] = in.StartCreateTime + " 00:00:00"
	}
	if in.EndCreateTime != "" {
		params["create_time <= ?"] = in.EndCreateTime + " 23:59:59"
	}
	if page <= 0 {
		page = 1
	}
	if pageSize == 0 {
		pageSize = 20
	}
	if sortField == "" {
		sortField = "uid"
	}
	if sortType == "" {
		sortType = "desc"
	}

	// 查询数量
	total, err := logic.SvcCtx.UserModel.GetResultsByTotal(logic.Ctx, params)
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}

	var users []*model.MallUser
	if total > 0 {
		err = logic.SvcCtx.UserModel.GetResultsByParams(logic.Ctx, &users, params, page, int8(pageSize), sortField+" "+sortType)
		if err != nil {
			return nil, status.Errorf(codes.Aborted, err.Error())
		}
	}

	userItems := []*user.User{}
	for _, value := range users {
		userItems = append(userItems, &user.User{
			Uid:        uint64(value.Uid),
			Name:       value.Name,
			Nick:       value.Nick,
			Email:      value.Email,
			Username:   value.Username,
			Password:   value.Password,
			AvatarUrl:  value.AvatarUrl,
			Source:     uint32(value.Source),
			Level:      uint32(value.Level),
			Mobile:     value.Mobile,
			Gender:     uint32(value.Gender),
			ProvinceId: uint32(value.ProvinceId),
			CityId:     uint32(value.CityId),
			DistrictId: uint32(value.DistrictId),
			Score:      uint32(value.Score),
			Status:     int32(value.Status),
			Note:       value.Note,
			CreateTime: value.CreateTime.String(),
			UpdateTime: value.UpdateTime.String(),
		})
	}

	pageTotal := math.Ceil(float64(total) / float64(pageSize))
	return &user.UserListResponse{
		Page:      page,
		PageSize:  pageSize,
		Total:     int32(total),
		PageTotal: int32(pageTotal),
		Users:     userItems,
	}, nil
}

/**
 * 列表
 *
 * @param uint64 Uid --------------------------非必传,用户Id
 * @param string EndCreateTime ----------------非必传,结束创建时间
 * @param string SortField --------------------非必传,排序字段
 * @param string SortType ---------------------非必传,排序方式
 * @param int32 PageSize ----------------------非必传,条数
 * @param uint32 Page -------------------------非必传,页码
 * @return *user.UserAlbumResponse, error
 * @author huwl
 */
func (logic *UserLogic) GetUserAlbum(in *user.GetUserAlbumRequest) (*user.UserAlbumResponse, error) {
	return &user.UserAlbumResponse{}, nil
}
